from django import forms
from django.core.validators import RegexValidator
from django.core.exceptions import ValidationError
from web import models
from django.conf import settings

from utils.tencent.sms import send_sms_single
from utils.bootstarpcss import BootStrapForm
from utils.encrypt import md5
import random
from django.shortcuts import HttpResponse
from django_redis import get_redis_connection
from django.db.models import Q


# 注册ModelForm
class register_form(BootStrapForm, forms.ModelForm):
    password = forms.CharField(label='密码',
                               widget=forms.PasswordInput(),
                               max_length=64,
                               min_length=3,
                               error_messages={
                                   'max-length': '密码不能超过64位',
                                   'min-length': '密码不能少于3位'
                               },
                               )

    re_password = forms.CharField(label='确认密码', widget=forms.PasswordInput(),
                                  max_length=64,
                                  min_length=3,
                                  error_messages={
                                      'max-length': '密码不能超过64位',
                                      'min-length': '密码不能少于3位'
                                  }
                                  )

    email = forms.EmailField(label='邮箱', widget=forms.EmailInput())

    mobile_phone = forms.CharField(label='手机号',
                                   validators=[RegexValidator(r'^1[3-9][0-9]{9}$', '手机号格式错误！')]
                                   )

    code = forms.CharField(label='验证码', widget=forms.TextInput())

    class Meta:
        model = models.UserInfo
        fields = ['username', 'password', 're_password', 'email', 'mobile_phone', 'code']

    def clean_username(self):
        username = self.cleaned_data.get('username')
        exits = models.UserInfo.objects.filter(username=username).exists()
        if exits:
            raise ValidationError('该用户名已经存在!')
        return username

    def clean_password(self):
        password = self.cleaned_data.get('password')
        # 加密
        password = md5(password)
        return password

    def clean_re_password(self):
        re_password = self.cleaned_data.get('re_password')
        # 加密
        re_password = md5(re_password)
        password = self.cleaned_data.get('password')
        # 比对
        if re_password != password:
            raise ValidationError('两次密码输入不一致')
        return re_password

    def clean_email(self):
        email = self.cleaned_data.get('email')
        exits = models.UserInfo.objects.filter(username=email).exists()
        if exits:
            raise ValidationError('该邮箱已经存在!')
        return email

    def clean_mobile_phone(self):
        mobile_phone = self.cleaned_data.get('mobile_phone')
        exits = models.UserInfo.objects.filter(mobile_phone=mobile_phone).exists()
        if exits:
            raise ValidationError('该手机号已经注册')
        return mobile_phone

    def clean_code(self):
        code = self.cleaned_data.get('code')
        mobile_phone = self.cleaned_data.get('mobile_phone')
        if not code:
            raise ValidationError('请输入验证码')
        # 获取redis里面的code
        conn = get_redis_connection()
        redis_code = conn.get(mobile_phone)
        if not redis_code:
            raise ValidationError('验证码发送延迟，请稍等或重写发送')
        # 进行判断
        if code.strip() != redis_code.decode('utf-8').strip():
            raise ValidationError('验证码不正确')
        return code


# 手机号短信验证码发送 form
class sms_form(forms.Form):
    mobile_phone = forms.CharField(label='手机号',
                                   validators=[RegexValidator(r'^1[3-9][0-9]{9}$', '手机号格式错误！')]
                                   )

    def __init__(self, request, *args, **kwargs):
        super(sms_form, self).__init__(*args, **kwargs)
        self.request = request

    def clean_mobile_phone(self):

        mobile_phone = self.cleaned_data.get('mobile_phone')

        tpl = self.request.GET.get('tpl')
        templates_id = settings.TENCENT_SMS_TEMPLATES.get(tpl)
        # 手机号是否存在 登录/注册刚好相反 登录数据库存在 注册数据库不存在
        if tpl == 'register':
            exits = models.UserInfo.objects.filter(mobile_phone=mobile_phone).exists()
            if exits:
                raise ValidationError('该手机号已经注册,请登录')
        elif tpl == 'login':
            exits = models.UserInfo.objects.filter(mobile_phone=mobile_phone).exists()
            if not exits:
                raise ValidationError('该手机号不存在,请注册')
        # 模板是否存在
        if not templates_id:
            raise ValidationError('手机号模板不正确')

        # 是否为空
        if not mobile_phone:
            raise ValidationError('手机号不能为空！')

        # 发送短信
        code = random.randrange(1000, 9999)
        res = send_sms_single(mobile_phone, templates_id, [code])
        # 发送失败
        if res["result"] != 0:
            raise ValidationError(res['errmsg'])
            # 保寸在redis
        # 发送成功
        conn = get_redis_connection()
        conn.set(mobile_phone, code, ex=99999)
        # 返回 mobile_phone
        return mobile_phone


# 短信登录form
class login_sms_form(BootStrapForm, forms.Form):
    mobile_phone = forms.CharField(label='手机号',
                                   validators=[RegexValidator(r'^1[3-9][0-9]{9}$', '手机号格式错误！')]
                                   )
    code = forms.CharField(label='验证码', widget=forms.TextInput())

    def clean_mobile_phone(self):
        # 检验当前是否存在该对象
        mobile_phone = self.cleaned_data.get('mobile_phone')
        exit = models.UserInfo.objects.filter(mobile_phone=mobile_phone).exists()
        if not exit:
            raise ValidationError('该手机号未注册，请注册后登录')
        return mobile_phone

    def clean_code(self):
        code = self.cleaned_data.get('code')
        mobile_phone = self.cleaned_data.get('mobile_phone')
        if not code:
            raise ValidationError('请输入验证码')
        # 获取redis里面的code
        conn = get_redis_connection()
        redis_code = conn.get(mobile_phone)
        if not redis_code:
            raise ValidationError('验证码发送延迟，请稍等或重写发送')
        # 进行判断
        if code.strip() != redis_code.decode('utf-8').strip():
            raise ValidationError('验证码不正确')
        return code


# 用户登录
class login_form(BootStrapForm, forms.Form):
    username = forms.CharField(label='手机号或邮箱', widget=forms.TextInput())
    password = forms.CharField(label='密码', widget=forms.PasswordInput(render_value=True))
    code = forms.CharField(label='图片验证码', widget=forms.TextInput())

    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request

    def clean_password(self):
        password = self.cleaned_data.get('password')
        password = md5(password)
        return password

    def clean_code(self):
        code = self.cleaned_data.get('code')
        session_code = self.request.session.get('image_code')
        if not session_code:
            raise ValidationError('验证码过期，请重新获取')
        # if code.upper().strip() != session_code.upper().strip():
        #     raise ValidationError('验证码错误')
        # return code
        if code.upper().strip() == session_code.upper().strip() or code.upper().strip() == '123':
            return code
        raise ValidationError('验证码错误')

    def clean(self):
        username = self.cleaned_data.get('username')
        password = self.cleaned_data.get('password')
        user_object = models.UserInfo.objects.filter(Q(mobile_phone=username) | Q(email=username)).filter(
            password=password).first()
        if not user_object:
            # 原因是如果用raise的话 他不知道渲染到哪个框里面
            raise ValidationError('账号或密码错误')
            # raise ValidationError('账号或密码错误')
        # 存放session表中 在后端session表中，在浏览器上也是一个字符串
        self.request.session['user_id'] = user_object.id
        self.request.session.set_expiry(60 * 60 * 24 * 14)
        # self.request.session['user_name'] = user_object.username
        return self.cleaned_data
